<template>
  <div>
    <el-form ref="form" label-width="80px">
      <el-upload
          class="upload-demo"
          v-loading="loading"
          drag
          action=""
          :auto-upload="false"
          :show-file-list="true"
          :on-change="changeFile"
          multiple>
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        <div class="el-upload__tip" slot="tip">文件大小不超过50MB</div>
      </el-upload>
    </el-form>
  </div>
</template>

<script>
import SparkMD5 from "spark-md5";
import axios from "axios";

export default {
  name: 'Home',
  data(){
    return {
      chunkSize: 5 * 1024 *1024,
      chunkUploadParam: {
        "data":null,
        "contentType":true,
        "processData":false
      },
      uploadId:"",
      loading: false
    }
  },
  methods: {
    async changeFile(file){
      this.loading = true;
      debugger;
      if (!file) return;
      const fileSize = file.size;
      const isLt2M = fileSize / 1024 / 1024 < 50;
      if (!isLt2M) {
        this.$message.error('上传文件大小不能超过 50MB!');
        this.loading = false;
        return;
      }
      if (fileSize <= this.chunkSize){
        this.$postReq("/sysFile/uploadSingleFile.do",{"file":file.raw},"multipart/form-data").then(resp => {
          if (resp.data.code === 200){
            this.$message.success("文件已上传");
          } else {
            this.$message.error(resp.msg.data);
          }
        }).catch(error => {
          this.$message.error("文件失败");
        })
        this.loading = false;
      } else {
        //分片上传
        //1、计算分片数量 剩余
        const chunkNum = Math.floor(fileSize / this.chunkSize);
        //获取文件内容MD5
        const fileMd5 = await this.getFileMd5(file);
        let isExist = false;
        //判断当前文件在桶中是否已存在
        await this.$req.get("/sysFile/existFile.do/" + fileMd5).then(resp => {
          if (resp.code === 200 && resp.data){
            isExist = true;
          }
        });
        if (isExist){
          this.$message.success("文件已上传");
          this.loading = false;
          return;
        }
        //向后端请求获取本次分片上传初始化
        await this.$req.get("/multipart/create.do?chunkNum="+chunkNum+"&fileName="+file.name+"&contentType="+file.raw.type)
            .then(resp => {
              if(resp.code === 200){
                const parts = resp.data.parts;
                this.uploadId = resp.data.uploadId;
                let item;
                for (item of parts){
                  //分片开始位置
                  let startSize = (item.parkNum - 1) * this.chunkSize;
                  //分片结束位置
                  let endSize = item.parkNum === chunkNum ? fileSize : startSize + this.chunkSize;
                  //获取当前分片的byte信息
                  let chunkFile = file.raw instanceof File ? file.raw.slice(startSize,endSize) : null;
                  this.uploadFilePear(item.uploadUrl,chunkFile,file.raw.type,item.parkNum);
                }
              } else {
                this.$message.error("文件调用后端进行分片失败");
              }

            });
        await this.completeChunkFile(chunkNum,file.name,file.raw.type,this.uploadId,fileMd5);
        this.loading = false;
      }
    },
    completeChunkFile(chunkNum,fileName,contentType,uploadId,fileMd5){
      this.$req.get("/multipart/complete.do?chunkNum="+chunkNum+"&fileName="+fileName+"&contentType="
          +contentType+"&uploadId="+uploadId+"&fileMd5="+fileMd5)
          .then(resp => {
            if (resp.code === 200){
              this.$message.success("文件上传成功");
              console.log("文件合并成功");
            }else {
              this.$message.error("文件上传失败");
            }
          });
    },
     uploadFilePear(uploadUrl,chunkFile,contentType,partNum){
      this.$putReq(uploadUrl,chunkFile,contentType).then(resp => {
        if (resp.data.status === 200){
          console.log("第" + partNum + "个分片上传完成");
        }
      }).catch(error => {
        console.log('分片：' + partNum + ' 上传失败，' + error)
      });
      },
    getFileMd5(file){
      let blob = new Blob([], { type: file.raw.type});
      const reader = new FileReader();
      reader.readAsBinaryString(file.raw);
      const sparkMD5 = new SparkMD5();
      return new Promise((resolve) => {
        reader.onload = (e) => {
          sparkMD5.append(e.target.result);
          resolve(sparkMD5.end());
        }
      })
    }
  }
}
</script>
